#include "AudioManager.h"
#include <spdlog/spdlog.h>
#include <stdexcept>

engine::resource::AudioManager::AudioManager()
{
	int flags = MIX_INIT_MP3 | MIX_INIT_OGG;
	if((Mix_Init(flags)&flags)!= flags)
	{
		spdlog::error("AudioManager构造失败 - SDL_mixer初始化失败: {}", Mix_GetError());
		throw std::runtime_error("AudioManager构造失败 - SDL_mixer初始化失败");
	}

	if (Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 2048))
	{
		spdlog::error("AudioManager构造失败 - SDL_mixer打开音频设备失败: {}", Mix_GetError());
		Mix_Quit();
		throw std::runtime_error("AudioManager构造失败 - SDL_mixer打开音频设备失败");
	}
}

engine::resource::AudioManager::~AudioManager()
{
	Mix_HaltChannel(-1);
	Mix_HaltMusic();
	clearSounds();
	clearMusics();
	Mix_CloseAudio();
	Mix_Quit();
	spdlog::trace("AudioManager析构成功");
}

Mix_Chunk* engine::resource::AudioManager::loadSound(const std::string& filePath)
{
	auto it = m_sounds.find(filePath);
	if (it != m_sounds.end())
	{
		return it->second.get();
	}

	Mix_Chunk* raw_chunk = Mix_LoadWAV(filePath.c_str());
	if (!raw_chunk)
	{
		spdlog::error("加载音效失败: {} - {}", filePath, Mix_GetError());
		return nullptr;
	}
	
	m_sounds.emplace(filePath, std::unique_ptr<Mix_Chunk, SDLMixChunkDeleter>(raw_chunk));
	spdlog::info("加载音效成功: {}", filePath);	
	return raw_chunk;
}

Mix_Chunk* engine::resource::AudioManager::getSound(const std::string& filePath)
{
	auto it = m_sounds.find(filePath);
	if (it != m_sounds.end())
	{
		return it->second.get();
	}
	spdlog::warn("获取音效失败: {} - 音效未加载", filePath);
	return loadSound(filePath);
}

void engine::resource::AudioManager::unloadSound(const std::string& filePath)
{
	auto it = m_sounds.find(filePath);
	if (it != m_sounds.end())
	{
		m_sounds.erase(it);
		spdlog::info("卸载音效成功: {}", filePath);
	}
	else
	{
		spdlog::warn("卸载音效失败: {} - 音效未加载", filePath);
	}
}

void engine::resource::AudioManager::clearSounds()
{
	if (!m_sounds.empty())
	{
		m_sounds.clear();
		spdlog::info("清除所有音效成功");
	}
	else
	{
		spdlog::warn("清除所有音效失败 - 音效资源为空");
	}
}

Mix_Music* engine::resource::AudioManager::loadMusic(const std::string& filePath)
{
	auto it = m_musics.find(filePath);
	if (it != m_musics.end())
	{
		return it->second.get();
	}

	Mix_Music* raw_music = Mix_LoadMUS(filePath.c_str());
	if (!raw_music)
	{
		spdlog::error("加载音乐失败: {} - {}", filePath, Mix_GetError());
		return nullptr;
	}
	m_musics.emplace(filePath, std::unique_ptr<Mix_Music, SDLMixMusicDeleter>(raw_music));
	spdlog::info("加载音乐成功: {}", filePath);	
	return raw_music;
}

Mix_Music* engine::resource::AudioManager::getMusic(const std::string& filePath)
{
	auto it = m_musics.find(filePath);
	if (it != m_musics.end())
	{
		return it->second.get();
	}
	spdlog::warn("获取音乐失败: {} - 音乐未加载", filePath);
	return loadMusic(filePath);
}

void engine::resource::AudioManager::unloadMusic(const std::string& filePath)
{
	auto it = m_musics.find(filePath);
	if (it != m_musics.end())
	{
		m_musics.erase(it);
		spdlog::info("卸载音乐成功: {}", filePath);
	}
	else
	{
		spdlog::warn("卸载音乐失败: {} - 音乐未加载", filePath);
	}
}

void engine::resource::AudioManager::clearMusics()
{
	if (!m_musics.empty())
	{
		m_musics.clear();
		spdlog::info("清除所有音乐成功");
	}
	else
	{
		spdlog::warn("清除所有音乐失败 - 音乐资源为空");
	}
}

void engine::resource::AudioManager::SDLMixChunkDeleter::operator()(Mix_Chunk* chunk) const noexcept
{
	if (chunk)
	{
		Mix_FreeChunk(chunk);
	}
}

void engine::resource::AudioManager::SDLMixMusicDeleter::operator()(Mix_Music* music) const noexcept
{
	if (music)
	{
		Mix_FreeMusic(music);
	}
}
